package org.whz.configuration;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.hazelcast.config.*;
import com.hazelcast.spi.merge.PutIfAbsentMergePolicy;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.discovery.DiscoveryClient;

import java.util.List;
import java.util.Map;

/**
 * @author whz-dell
 */
@Slf4j
@AllArgsConstructor
public class HazelcastConfig {
    private DiscoveryClient client;
    private HazelcastProperties hazelcastProperties;

    public Config hazelcastConfig() {
        // event store
        Config config = new Config();
        for (Map.Entry<String, HazelcastProperties.ServerConfig> entry : hazelcastProperties.getConfigs().entrySet()) {
            MapConfig eventStoreMap = createMap(
                    entry.getValue().getMaxCount(),
                    entry.getValue().getBatchCount(),
                    entry.getValue().getBackUpCount(),
                    entry.getKey());

            config.addMapConfig(eventStoreMap);
        }
        config.setProperty("hazelcast.jmx", "true");

        List<String> ips = obtainClusterIps();
        log.info("health-check cluster ips;{}", JSON.toJSONString(ips));

        if (hazelcastProperties.isEnableCluster() && ips.size() > 1) {
            config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(true);
            TcpIpConfig tcpIpConfig = config.getNetworkConfig().getJoin().getTcpIpConfig();
            tcpIpConfig.setEnabled(true);
            tcpIpConfig.setMembers(ips);
        }
        return config;
    }

    private static MapConfig createMap(int maxCount, int batchSize, int backUpCount, String name) {
        MapConfig config = new MapConfig(name);

        config.setInMemoryFormat(InMemoryFormat.OBJECT)
                .setBackupCount(backUpCount)
                .getEvictionConfig()
                .setEvictionPolicy(EvictionPolicy.LFU)
                .setSize(maxCount)
                .setMaxSizePolicy(MaxSizePolicy.FREE_HEAP_SIZE);

        config.setMergePolicyConfig(new MergePolicyConfig(PutIfAbsentMergePolicy.class.getName(), batchSize));
        return config;
    }


    private List<String> obtainClusterIps() {
        if (client == null) {
            log.warn("health check has not get discovery client.");
            return Lists.newArrayList("127.0.0.1");
        }
        List<String> ips = Lists.newArrayList();
        client.getInstances(hazelcastProperties.getAppName()).forEach(instance -> ips.add(instance.getHost()));
        return ips;
    }
}